package server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import message.Message;
import message.PingRequestMessage;
import message.ServerMessageWrapper;
import message.messageFactory.MessageFactory;

public class Connection
{
	private PrintWriter out;
	private BufferedReader in;
	private Socket socket;
	public final int connectionId;
	private long lastActivityTimestamp;
	private boolean canBePinged;
	private static final MessageFactory messageFactory;
	private boolean isServerConnection;
	
	static
	{
		messageFactory = MessageFactory.getInstance();
	}
	
	public Connection(int connectionId, Socket socket) throws InstantiationException
	{
		this.socket = socket;
		this.connectionId = connectionId;
		lastActivityTimestamp = System.currentTimeMillis();
		canBePinged = true;
		
		try
		{
			out = new PrintWriter(socket.getOutputStream(), true);
			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		}
		catch (IOException e)
		{
			throw new InstantiationException();
		}
	}
	public boolean isServerConnection()
	{
		return isServerConnection;
	}
	public void setIsServerConnection(boolean isServerConnection)
	{
		this.isServerConnection = isServerConnection;
	}
	public Message getMessage()
	{
		Message message = null;
		
		try
		{
			message = messageFactory.unserializeMessage(in.readLine());
		}
		catch (IOException e) {}
		
		if (message != null)
		{
			lastActivityTimestamp = System.currentTimeMillis();
			canBePinged = true;
			
			return new ServerMessageWrapper(message, this.connectionId, isServerConnection);
		}
		else
			return null;
	}
	public boolean hasMessage()
	{
		try
		{
			return in.ready();
		}
		catch (IOException e)
		{
			e.printStackTrace();
			return false;
		}
	}
	public void close() throws IOException
	{
		socket.close();
	}
	public void sendMessage(Message message)
	{
		out.println(messageFactory.serializeMessage(message));
		
		if (message.getClass().equals(PingRequestMessage.class))
			canBePinged = false;
	}
	public long getInactivityTime()
	{
		return System.currentTimeMillis() - lastActivityTimestamp;
	}
	public boolean canBePinged()
	{
		return canBePinged;
	}
}
